#if 0
//设置核为3*3的均值滤波处理灰度图像
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;


void blur_zj(Mat &a, Mat &b)
{
	int i, j;
	for (i = 1; i < a.rows; i++)          //因为核为3*3，所以不能从0，0开始
	{
		for (j = 1; j < a.cols; j++)
		{
			if ((i + 1) < a.rows && (j + 1) < a.cols && (i - 1) >= 0 && (j - 1) >= 0)//因为核为3*3，所以靠近边缘的一个像素不能被处理
			{
				b.at<uchar>(i, j) = (a.at<uchar>(i - 1, j) + a.at<uchar>(i, j - 1) + a.at<uchar>(i + 1, j - 1) + a.at<uchar>(i - 1, j) + a.at<uchar>(i, j) + a.at<uchar>(i + 1, j) + a.at<uchar>(i - 1, j + 1)+ a.at<uchar>(i, j + 1) + a.at<uchar>(i + 1, j + 1)) / 9;
				
			}
			else             //边缘像素不变
			{
				b.at<uchar>(i, j) = a.at<uchar>(i, j);
			}
		}
	}
}
int main()
{
	Mat a = imread("1.jpg", 0),b;
	a.copyTo(b);                 //需要让b是个矩阵，如果没有给b指向空间的话，执行 blur_zj(a, b);的赋值会报错因为此时b没有东西所以b.at<uchar>(i, j)会，，
	imshow("原图", a);          //应该用复制或克隆，赋值的话有可能边运算边更改
    blur_zj(a, b);
	imshow("自己写的滤波", b);
	blur(a, b, Size(3, 3), Point(-1, -1));
	imshow("官方", b);


	waitKey(0);
	return 0;
}
#endif
//自写均值滤波处理灰度图像

#if 0
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//设置核为3*3的高斯滤波处理灰度图像

//定义高斯函数所需要的，，，
double sigma = 2;//设置标准差，因为运算的是小数，所以用double
double pai = 3.1415;

double sum_zj=0.0;  //归一化,为防止与c++库里的sum变量相冲突，改了一下
double gs[3][3] = { 0 };
int size_zj = 3;          //设置尺寸为3*3的核
void gshe(Mat& a)
{
	int i, j;
	for (i = 0; i < size_zj; i++)
	{
		for (j = 0; j < size_zj; j++)               //x的平方和y的平方分别表示的是邻域内其他像素与邻域内中心像素的距离，所以要写成这样
		{
			gs[i][j] = (1 / (2 * pai * sigma * sigma)) * exp(-((i- size_zj/2) * (i - size_zj / 2) + (j - size_zj / 2) * (j - size_zj / 2)) / (2 * sigma * sigma));
			sum_zj += gs[i][j];
		}
	}
	for (i = 0; i < size_zj; i++)
	{
		for (j = 0; j < size_zj; j++)
		{
			gs[i][j] = gs[i][j] / sum_zj;
			printf("% lf" , gs[i][j]);
		}
		printf("\n");
	}
}
void GaussianBlur_zj(Mat& a, Mat& b)
{
	int i, j,c,d;
	
	for (i = 1; i < a.rows; i++)          //因为核为3*3，所以不能从0，0开始
	{
		for (j = 1; j < a.cols; j++)
		{
			if ((i + 1) < a.rows && (j + 1) < a.cols && (i - 1) >= 0 && (j - 1) >= 0)//因为核为3*3，所以靠近边缘的一个像素不能被处理
			{
				
				b.at<uchar>(i, j) = a.at<uchar>(i - 1, j - 1) * gs[0][0] + a.at<uchar>(i - 1, j) * gs[0][1] + a.at<uchar>(i - 1, j + 1) * gs[0][2] + a.at<uchar>(i, j - 1) * gs[1][0] + a.at<uchar>(i, j) * gs[1][1] + a.at<uchar>(i, j + 1) * gs[1][2] + a.at<uchar>(i + 1, j - 1) * gs[2][0] + a.at<uchar>(i + 1, j) * gs[2][1] + a.at<uchar>(i + 1, j + 1) * gs[2][2];
			}
			else             //边缘不变
			{
				b.at<uchar>(i, j) = a.at<uchar>(i, j);
			}
		}
	}
}
int main()
{
	Mat a = imread("1.jpg", 0),b;
	a.copyTo(b);
	imshow("原图", a);   
	gshe(a);
	GaussianBlur_zj(a, b);
	imshow("自己写的滤波", b);
	GaussianBlur(a, b, Size(3, 3), 2);
	imshow("官方", b);
	waitKey(0);
	return 0;
}
#endif
//自写高斯滤波处理灰度图像

#if 1
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//设置核为3*3的双边滤波处理灰度图像

//定义双边函数所需要的，，，
double sigma_d=100;//设置标准差，因为运算的是小数，所以用double
double sigma_r = 100;

double js1, js2=0;//储存数据
double sum_zj = 0.0;  //归一化,为防止与c++库里的sum变量相冲突，改了一下,用来表示分母
double sum1_zj = 0.0;  //用来表示分子
double sb[3][3] = { 0 }, sb1[3][3] = { 0 }, sbz[3][3] = {0};   //一个定义域核一个是值域核一个计算他俩相乘
int dsize = 3;          //设置尺寸为3*3的核
int zx1, zx2;      //核的中心值

void sbhe(Mat& a,int zx1,int zx2)
{
	int c, d,ii,jj;
	for (ii = (zx1 - dsize / 2),c=0; ii <= (zx1+dsize/2),c<dsize; ii++,c++)
	{
		for (jj = (zx2 - dsize / 2),d=0; jj <= (zx2 + dsize / 2),d<dsize; jj++,d++)              
		{
			sb[c][d] = exp(-((ii - zx1) * (ii - zx1) + (jj -zx2) * (jj -zx2)) / (2 * sigma_d * sigma_d));
			sb1[c][d] = exp(-pow((a.at<uchar>(ii, jj)- a.at<uchar>(zx1, zx2)),2) / (2 * sigma_r * sigma_r));
			sbz[c][d] = sb[c][d] * sb1[c][d];        //算出w

			sum_zj += sbz[c][d];               //算出分母
			//printf("%lf", sbz[c][d]);//检测
		}
		//printf("\n");
	}
	for (ii = (zx1 - dsize / 2), c = 0; ii <= (zx1 + dsize / 2), c < dsize; ii++, c++)
	{
		for (jj = (zx2 - dsize / 2), d = 0; jj <= (zx2 + dsize / 2), d < dsize; jj++, d++)
		{
			js1 = a.at<uchar>(ii, jj) * sbz[c][d]/ sum_zj ;
			js2 += js1;
			/*printf("%lf\n", js2);*/
		}
	}
	
}
void bilateralFilter_zj(Mat& a, Mat& b)
{
	int i, j;
	

	for (i = 1; i < a.rows; i++)          //因为核为3*3，所以不能从0，0开始
	{
		for (j = 1; j < a.cols; j++)
		{
			if ((i + 1) < a.rows && (j + 1) < a.cols && (i - 1) >= 0 && (j - 1) >= 0)//因为核为3*3，所以靠近边缘的一个像素不能被处理
			{
				/*zx1 = i;
				zx2 = j;*/
				sbhe(a,i,j);
				b.at<uchar>(i, j) = js2;
				js1 = 0;
				js2 = 0;
				sum_zj = 0;    //一定要记得重新赋值，清除之前的值，我永远不会忘了因为这个错误改了多久
				
			}
			else             //边缘不变
			{
				b.at<uchar>(i, j) = a.at<uchar>(i, j);
			}
		}
	}
	
}
int main()
{
	Mat a = imread("1.jpg", 0), b;
	a.copyTo(b);
	imshow("原图", a);
	
	bilateralFilter_zj(a, b);
	imshow("自己写的滤波", b);
	bilateralFilter(a, b, 3,100,100);
	imshow("官方", b);
	waitKey(0);
	return 0;
}
#endif
//自写双边滤波处理灰度图像